/*
 * declare_parser.c
 *
 *  Created on: 2013-4-30
 *      Author: xkaying
 */

#include "declare_parser.h"
#include "declare_expression.h"

#include "../common/list.h"
#include "../common/token.h"
#include "../common/InversePoland.h"
#include "../common/symboltable.h"
//
#include <assert.h>
#include <stdlib.h>
#include <stdio.h>

struct _declarelex
{
	//定义位置
	List *ptokenlist;
	int len; //总共读取的长度
	ListCursor *pcursor;
};

void DeclareLexDispose(DeclareLex *plex)
{
	if (plex) {
		Token *ptoken;
		ptoken = (Token*) ListPop(plex->ptokenlist);
		while (ptoken) {
			free(ptoken);
			ptoken = (Token*) ListPop(plex->ptokenlist);
		}
		free(plex);
	}
}

//对定义部分进行词法解析,获取每个表达式的符号
DeclareLex *
DeclareLexer(char *buff, int size)
{
	//对数组部分,进行关键字解析
	DeclareLex *plex;
	plex = (DeclareLex*) malloc(sizeof(DeclareLex));
	plex->ptokenlist = ListInit(0);
	plex->pcursor = ListGetCursor(plex->ptokenlist);
	////////
	char *pch;
	pch = buff; //表示当前位置
	int len;
	len = 0;
	int state;
	state = 0;
	int line;
	line = 1;
	Token *ptoken;
	ptoken = 0;

	char tokenbuff[128];
	int tokenlen;
	tokenlen = 0;

	while (len < size) {
		//printf("%c",*pch);
		//printf(" state %d-%d:%d \n",len,size,state);
		//解析{ 和} 这中间才是declare的内容,自动跳过空格,table等.
		switch (state)
		{
			//0
			case 0: {
				switch (*pch)
				{
					case '{': {
						//1表示可以开始读取正式表达式
						state = 1;
						len++;
						pch++;
						continue;
					}
					case ';': {
						//10表示0状态下的注释
						state = 10;
						len++;
						pch++;
						continue;
					}
					case '\n': {
						line++;
					}
					case '\t':
					case ' ': {
						len++;
						pch++;
						continue;
					}
					default: {
						printf("第%d行:declare模块内容需要使用{}包含,请在%c前面加上{.\n", line,
								buff[len]);
						//释放declare lex
						DeclareLexDispose(plex);
						return 0;
					}
				}
				printf("declare lexer状态机错误.\n");
				return 0;
			}
			case 10: {
				switch (*pch)
				{
					case '\n': {
						state = 1;
						line++;
						len++;
						pch++;
						continue;
					}
					default: {
						len++;
						pch++;
						continue;
					}
				}
				printf("declare lexer状态机错误.\n");
				return 0;
			}
			case 1: {
				switch (*pch)
				{
					//表示读取结束,返回lex
					case '}': {
						len++;
						plex->len = len;
						return plex;
					}
					case ';': {
						//11 表示内容中的注释
						state = 11;
						len++;
						pch++;
						continue;
					}
					case '\n': {
						line++;
					}
					case '\t':
					case ' ': {
						len++;
						pch++;
						continue;
					}
					default: {
						if ((((*pch) >= 'a') && ((*pch) <= 'z'))
								|| (((*pch) >= 'A') && ((*pch) <= 'Z'))
								|| ((*pch) == '_')) {
							//12表示读取token
							state = 12;
							ptoken = (Token*) malloc(sizeof(Token));
							tokenbuff[0] = *pch;
							tokenlen = 1;
							ptoken->type = TokenType_Variable;
							ptoken->line = line;
							len++;
							pch++;
							continue;
						}
						//如果是其他值,则表示是不可识别字符
						printf("第%d行:不可识别的标签字符,字符标签应该以\"a-z\" \"A-Z\" \"_\"开始",
								line);
						DeclareLexDispose(plex);
						return 0;
					}
				}
				printf("declare lexer状态机错误.\n");
				return 0;
			}
			case 11: {
				switch (*pch)
				{
					case '\n': {
						state = 1;
						line++;
						len++;
						pch++;
						continue;
					}
					default: {
						len++;
						pch++;
						continue;
					}
				}
				printf("declare lexer状态机错误.\n");
				return 0;
			}
			case 12: {
				if ((((*pch) >= 'a') && ((*pch) <= 'z'))
						|| (((*pch) >= 'A') && ((*pch) <= 'Z'))
						|| ((*pch) == '_')
						|| (((*pch) >= '0') && ((*pch) <= '9'))) {
					//12表示读取token
					tokenbuff[tokenlen] = *pch;
					tokenlen++;
					len++;
					pch++;
					continue;
				}
				if ((*pch) == ':') {
					//进入读取表达式阶段
					//13表示读取:号以便进入表达式读取
					tokenbuff[tokenlen] = '\0';
					ptoken->name = SymbolTablePush(tokenbuff);
					//将符号压入列表中
					ListPush(plex->ptokenlist, ptoken);
					//将 :压入解析列表
					ptoken = (Token*) malloc(sizeof(Token));
					ptoken->type = TokenType_DeclareExpressionStart;
					ptoken->line = line;
					ListPush(plex->ptokenlist, ptoken);
					state = 14;
					len++;
					pch++;
					continue;
				}
				if ((*pch) == '\n') {
					//等待读取 :
					line++;
					//13表示读取:号以便进入表达式读取
					tokenbuff[tokenlen] = '\0';
					ptoken->name = SymbolTablePush(tokenbuff);
					//将符号压入列表中
					ListPush(plex->ptokenlist, ptoken);
					state = 13;
					len++;
					pch++;
					continue;
				}
				if ((*pch) == '\t' || (*pch) == ' ') {
					//等待读取 :
					state = 13;
					tokenbuff[tokenlen] = '\0';
					ptoken->name = SymbolTablePush(tokenbuff);
					//将符号压入列表中
					ListPush(plex->ptokenlist, ptoken);
					len++;
					pch++;
					continue;
				}
				//其他的一些字符,表示读取出错
				printf("第%d行:错误的declare表达式语句.\n", line);
				DeclareLexDispose(plex);
				return 0;
			}
			case 13: {
				switch (*pch)
				{
					case '\n': {
						line++;
					}
					case ' ':
					case '\t': {
						len++;
						pch++;
						continue;
					}
					case ':': {
						state = 14;
						ptoken = (Token*) malloc(sizeof(Token));
						ptoken->type = TokenType_DeclareExpressionStart;
						ptoken->line = line;
						ListPush(plex->ptokenlist, ptoken);
						len++;
						pch++;
						continue;
					}
					default: {
						printf("第%d行:错误的declare表达式语句.\n", line);
						DeclareLexDispose(plex);
						return 0;
					}
				}
				printf("declare lexer状态机错误.\n");
				return 0;
			}
			case 14: {
				//读取表达式,以及符号,放入列表
				switch (*pch)
				{
					case '\'': {
						//读取单个数值,并放入列表,进入状态15
						state = 15;
						ptoken = (Token*) malloc(sizeof(Token));
						ptoken->type = TokenType_String;
						ptoken->line = line;
						tokenlen = 0;
						len++;
						pch++;
						continue;
					}
					case '-': {
						ptoken = (Token*) malloc(sizeof(Token));
						ptoken->type = TokenType_DeclareLess;
						ptoken->line = line;
						ListPush(plex->ptokenlist, ptoken);
						ptoken = 0;
						len++;
						pch++;
						continue;
					}
					case '+': {
						ptoken = (Token*) malloc(sizeof(Token));
						ptoken->type = TokenType_DeclareMore;
						ptoken->line = line;
						ListPush(plex->ptokenlist, ptoken);
						ptoken = 0;
						len++;
						pch++;
						continue;
					}
					case '~': {
						ptoken = (Token*) malloc(sizeof(Token));
						ptoken->type = TokenType_DeclareBetween;
						ptoken->line = line;
						ListPush(plex->ptokenlist, ptoken);
						ptoken = 0;
						len++;
						pch++;
						continue;
					}
					case '|': {
						ptoken = (Token*) malloc(sizeof(Token));
						ptoken->type = TokenType_DeclareOr;
						ptoken->line = line;
						ListPush(plex->ptokenlist, ptoken);
						ptoken = 0;
						len++;
						pch++;
						continue;
					}
					case '\n': {
						line++;
					}
					case '\t':
					case ' ': {
						len++;
						pch++;
						continue;
					}
					case '0': {
						//表示可能读取16进制字符,进入状态16
						state = 16;
						len++;
						pch++;
						continue;
					}
					case ';': {
						//表示处理结束
						ptoken = (Token*) malloc(sizeof(Token));
						ptoken->type = TokenType_DeclareExpressionEnd;
						ptoken->line = line;
						ListPush(plex->ptokenlist, ptoken);
						ptoken = 0;
						len++;
						pch++;
						// 跳转到其他语句,读取到回车
						state = 141;
						continue;
					}
					default: {
						//表示读取关键字
						//进入状态17
						if ((((*pch) >= 'a') && ((*pch) <= 'z'))
								|| (((*pch) >= 'A') && ((*pch) <= 'Z'))
								|| ((*pch) == '_')) {
							//12表示读取token
							state = 17;
							ptoken = (Token*) malloc(sizeof(Token));
							tokenbuff[0] = *pch;
							tokenlen = 1;
							ptoken->type = TokenType_Variable;
							ptoken->line = line;
							len++;
							pch++;
							continue;
						}
						printf("第%d行:错误的declare表达式语句.不能处理字符%c.\n", line, *pch);
						DeclareLexDispose(plex);
						return 0;
					}
				}
				printf("declare lexer状态机错误.\n");
				return 0;
			}
			case 15: {
				if (((*pch) >= 33) && ((*pch) <= 126)) {
					//表示是可显示字符,放入到
					tokenbuff[tokenlen] = *pch;
					tokenlen++;
					len++;
					pch++;
					//151表示读取 '
					state = 151;
					continue;
				}
				//表示出错,未知字符
				printf("第%d行:错误的declare表达式语句.单引号''中的字符是未知字符\n", line);
				DeclareLexDispose(plex);
				return 0;
			}
			case 151: {
				if ((*pch) == '\'') {
					//表示结束
					tokenbuff[tokenlen] = '\0';
					ptoken->name = SymbolTablePush(tokenbuff);
					ListPush(plex->ptokenlist, ptoken);
					ptoken = 0;
					len++;
					pch++;
					state = 14;
					continue;
				}
				else if ((*pch) == '\n') {
					//表示,应该是单引号漏了
					printf("第%d行:单引号''缺少了一半,请补全.\n", line);
					DeclareLexDispose(plex);
					return 0;
				}
				else {
					//其他字符,提出警告并且跳过
					printf("第%d行:警告,单引号''中的字符只能有一个,字符%c被忽略\n", line, *pch);
					len++;
					pch++;
					continue;;
				}
				printf("declare lexer状态机错误.\n");
				return 0;

			}
			case 16: {
				if (((*pch) == 'x') || ((*pch) == 'x')) {
					state = 161;
					ptoken = (Token*) malloc(sizeof(Token));
					tokenlen = 0;
					ptoken->type = TokenType_Value;
					ptoken->line = line;
					len++;
					pch++;
					continue;
				}
				printf("第%d行:错误的数值表达方法.你应该输入0x**,来表示16进制数.\n", line);
				DeclareLexDispose(plex);
				return 0;
			}
			case 161: {
				if (((*pch) >= '0') && ((*pch) <= '9')) {
					tokenbuff[tokenlen] = *pch;
					tokenlen++;
					len++;
					pch++;
					continue;
				}
				if (((*pch) == ' ') || ((*pch) == '\n') || ((*pch) == '\t')
						|| ((*pch) == '-') || ((*pch) == '+') || ((*pch) == '~')
						|| ((*pch) == '|') || ((*pch) == ';')) {
					state = 14;
					tokenbuff[tokenlen] = '\0';
					ptoken->name = SymbolTablePush(tokenbuff);
					ListPush(plex->ptokenlist, ptoken);
					ptoken = 0;
					continue;
				}
				if (((*pch) >= 'a') && ((*pch) <= 'f')) {
					tokenbuff[tokenlen] = *pch;
					tokenlen++;
					len++;
					pch++;
					continue;
				}
				if (((*pch) >= 'A') && ((*pch) <= 'F')) {
					tokenbuff[tokenlen] = *pch;
					tokenlen++;
					len++;
					pch++;
					continue;
				}
				printf("第%d行:错误的数值表达.只能使用0~9 a~f.不能识别: %c .\n", line, *pch);
				DeclareLexDispose(plex);
				return 0;
			}
			case 17: {
				//处理字符串
				if ((((*pch) >= 'a') && ((*pch) <= 'z'))
						|| (((*pch) >= 'A') && ((*pch) <= 'Z'))
						|| ((*pch) == '_')
						|| (((*pch) >= '0') && ((*pch) <= '9'))) {
					//12表示读取token
					tokenbuff[tokenlen] = *pch;
					tokenlen++;
					len++;
					pch++;
					continue;
				}
				if (((*pch) == ' ') || ((*pch) == '\n') || ((*pch) == '\t')
						|| ((*pch) == '-') || ((*pch) == '+') || ((*pch) == '~')
						|| ((*pch) == '|') || ((*pch) == ';')) {
					state = 14;
					tokenbuff[tokenlen] = '\0';
					ptoken->name = SymbolTablePush(tokenbuff);
					ListPush(plex->ptokenlist, ptoken);
					ptoken = 0;
					continue;
				}
				printf("第%d行:错误的标识命名.只能使用a~z A~Z _.不能识别: %c.\n", line, *pch);
				DeclareLexDispose(plex);
				return 0;
			}
			case 141: {
				if (*pch == '\n') {
					state = 1;
					len++;
					line++;
					pch++;
					continue;
				}
				len++;
				pch++;
				continue;
			}
			default: {
				printf("错误的状态标识:%d.\n", state);
				DeclareLexDispose(plex);
				return 0;
			}
		}

	}
////////////
	printf("文本扫描结束,未发现declare模块的结尾.");
	DeclareLexDispose(plex);
	return 0;
}

void DeclareInversePolandPrepare(List *ptokenlist)
{
	assert(ptokenlist);
	ListCursor *pcursor;
	pcursor = ListGetCursor(ptokenlist);
	//
	Token *ptoken;
	ptoken = (Token*) ListForeach(ptokenlist, pcursor);
	while (ptoken) {
		if (ptoken->type == TokenType_DeclareLess) {
			//在-号后面,加入0值
			ListInsert(ptokenlist, TokenInit(TokenType_None), pcursor);
		}
		else if (ptoken->type == TokenType_DeclareMore) {
			ListInsert(ptokenlist, TokenInit(TokenType_None), pcursor);
		}
		ptoken = (Token*) ListForeach(ptokenlist, pcursor);
	}
}

int DeclareInversePoland(Stack *poutput, Token *ptoken, Stack *pstore)
{
	assert(poutput);
	assert(ptoken);
	assert(pstore);
	switch (ptoken->type)
	{
		case TokenType_Variable:
		case TokenType_Value:
		case TokenType_None:
		case TokenType_String: {
			StackPush(poutput, ptoken);
			return 1;
		}
		case TokenType_DeclareOr: {
			Token *pttoken;
			pttoken = (Token*) StackPop(pstore);
			while (pttoken) {
				StackPush(poutput, pttoken);
				pttoken = (Token*) StackPop(pstore);
			}
			StackPush(pstore, ptoken);

			return 1;
		}
		case TokenType_DeclareMore: {
			Token *pttoken;
			pttoken = (Token*) StackData(pstore);
			while (pttoken) {
				if (pttoken->type == TokenType_DeclareOr) {
					StackPush(pstore, ptoken);
					return 1;
				}
				else {
					StackPush(poutput, StackPop(pstore));
					pttoken = (Token*) StackData(pstore);
				}
			}
			StackPush(pstore, ptoken);
			return 1;
		}
		case TokenType_DeclareLess: {
			Token *pttoken;
			pttoken = (Token*) StackData(pstore);
			while (pttoken) {
				if (pttoken->type == TokenType_DeclareOr) {
					StackPush(pstore, ptoken);
					return 1;
				}
				else {
					StackPush(poutput, StackPop(pstore));
					pttoken = (Token*) StackData(pstore);
				}
			}
			StackPush(pstore, ptoken);
			return 1;
		}
		case TokenType_DeclareBetween: {
			Token *pttoken;
			pttoken = (Token*) StackData(pstore);
			while (pttoken) {
				if (pttoken->type == TokenType_DeclareOr) {
					StackPush(pstore, ptoken);
					return 1;
				}
				else {
					StackPush(poutput, StackPop(pstore));
					pttoken = (Token*) StackData(pstore);
				}
			}
			StackPush(pstore, ptoken);
			return 1;
		}
		default: {
			printf("declare逆波兰状态错误.\n");
			return 0;
		}
			;
	}
	printf("declare逆波兰状态错误.\n");
	return 0;
}
//对定义部分进行语法解析,获取定义表达式
DeclareExpression *DeclareParser(DeclareLex *plex)
{
	assert(plex);
	DeclareExpression *pde;
	List *ptokenlist;
	ptokenlist = ListInit(0);
	Stack *ptokenstack;
	pde = 0;
	int state = 0;
//0表示初始状态,读取命名
//解析每一个语句
	Token *ptoken;
	ptoken = (Token*) ListExport(plex->ptokenlist);
	if (ptoken == 0) {
		//表示读取结束
		return 0;
	}
	while (ptoken) {
		switch (state)
		{
			case 0: {
				//初始状态,读取变量名字
				if (ptoken->type == TokenType_Variable) {
					//2表示读取入口函数
					state = 1;
					pde = DeclareExpressionCreate(ptoken);
					ptoken = (Token*) ListExport(plex->ptokenlist);
					continue;
				}
				//;号 表示跳过该符号
				if (ptoken->type == TokenType_DeclareExpressionEnd) {
					ptoken = (Token*) ListExport(plex->ptokenlist);
					continue;
				}
				//其他表示语法错误
				printf("第%d行:错误的declare表达式定义!必需先定义表达式名称!\n", ptoken->line);
				return 0;
			}
			case 1: {
				//状态1 表示,只读取 : 其他都是错误的
				if (ptoken->type == TokenType_DeclareExpressionStart) {
					state = 2;
					free(ptoken);
					ptoken = (Token*) ListExport(plex->ptokenlist);
					continue;
				}
				printf("第%d行:错误的declare表达式定义!表达式名称后面需要跟随':'号!\n", ptoken->line);
				return 0;
			}
			case 2: {
				//状态2开始读取其他东西,比如 变量,字符串,数值 或者 符号,并推演成逆波兰表达式
				switch (ptoken->type)
				{
					case TokenType_Variable:
					case TokenType_Value:
					case TokenType_String: {
						state = 3;	//表示读取操作符号状态
						//把当前符号放入临时列表
						//
						ListPush(ptokenlist, ptoken);
						ptoken = (Token*) ListExport(plex->ptokenlist);
						continue;
					}
					case TokenType_DeclareOr:
					case TokenType_DeclareLess:
					case TokenType_DeclareMore:
					case TokenType_DeclareBetween: {
						printf("第%d行:错误的declare表达式定义!操作符号%c使用错误!\n",
								ptoken->line, ptoken->name[0]);
						return 0;
					}
					default: {
						printf("第%d行:错误的declare表达式定义!不支持的操作符号或未知字符.\n",
								ptoken->line);
						return 0;
					}
				}
				printf("declare parser状态机错误.\n");
				return 0;
			}
			case 3: {
				switch (ptoken->type)
				{
					case TokenType_Variable:
					case TokenType_Value:
					case TokenType_String: {
						printf("第%d行:错误的declare表达式定义!%s前面缺少操作符号.\n",
								ptoken->line, ptoken->name);
						return 0;
					}
					case TokenType_DeclareOr: {
						state = 2;
						ListPush(ptokenlist, ptoken);
						ptoken = (Token*) ListExport(plex->ptokenlist);
						continue;
					}
					case TokenType_DeclareLess:
					case TokenType_DeclareMore: {
						state = 4;	//表示进入集合,集合后面只能是结束符号或者|
						ListPush(ptokenlist, ptoken);
						ptoken = (Token*) ListExport(plex->ptokenlist);
						continue;
					}

					case TokenType_DeclareBetween: {
						state = 31;	//表示读取操作符号状态
						ListPush(ptokenlist, ptoken);
						ptoken = (Token*) ListExport(plex->ptokenlist);
						continue;
					}
					case TokenType_DeclareExpressionEnd: {
						//表示读取结束,返回表达式
						free(ptoken);
						//进行逆波兰转换
						DeclareInversePolandPrepare(ptokenlist);
						ptokenstack = InversePoland(ptokenlist,
								DeclareInversePoland);
						if (!ptokenstack) {
							return 0;
						}
						DeclareExpressionSet(pde, ptokenstack);
						return pde;
					}
					default: {
						printf("第%d行:错误的declare表达式定义!\n", ptoken->line);
						return 0;
					}
				}
				printf("declare parser状态机错误.\n");
				return 0;
			}
			case 31: {
				//读取操作符号状态
				switch (ptoken->type)
				{
					case TokenType_Variable:
					case TokenType_Value:
					case TokenType_String: {
						state = 4;	//between读取结束
						//把当前符号放入临时列表
						//
						ListPush(ptokenlist, ptoken);
						ptoken = (Token*) ListExport(plex->ptokenlist);
						continue;
					}
					case TokenType_DeclareOr:
					case TokenType_DeclareLess:
					case TokenType_DeclareMore:
					case TokenType_DeclareBetween: {
						printf("第%d行:错误的declare表达式定义!~后面不能跟随操作符号%c!\n",
								ptoken->line, ptoken->name[0]);
						return 0;
					}
					default: {
						printf("第%d行:错误的declare表达式定义!~后面不能跟随%c!\n",
								ptoken->line, ptoken->name[0]);
						return 0;
					}
				}
				printf("declare parser状态机错误.\n");
				return 0;
			}
			case 4: {
				//只能接|
				switch (ptoken->type)
				{
					case TokenType_Variable:
					case TokenType_Value:
					case TokenType_String: {
						printf("第%d行:错误的declare表达式定义!%s前面缺少操作符号.\n",
								ptoken->line, ptoken->name);
						return 0;
					}
					case TokenType_DeclareLess:
					case TokenType_DeclareMore:
					case TokenType_DeclareBetween: {
						printf("第%d行:错误的declare表达式定义!~后面不能跟随操作符号%c!\n",
								ptoken->line, ptoken->name[0]);
						return 0;
					}
					case TokenType_DeclareOr: {
						state = 2;
						ListPush(ptokenlist, ptoken);
						ptoken = (Token*) ListExport(plex->ptokenlist);
						continue;
					}
					case TokenType_DeclareExpressionEnd: {
						//表示读取结束,返回表达式
						free(ptoken);
						//进行逆波兰转换
						DeclareInversePolandPrepare(ptokenlist);
						ptokenstack = InversePoland(ptokenlist,
								DeclareInversePoland);
						if (!ptokenstack) {
							return 0;
						}
						DeclareExpressionSet(pde, ptokenstack);
						return pde;
					}
					default: {
						printf("第%d行:错误的declare表达式定义!\n", ptoken->line);
						return 0;
					}
				}
				printf("declare parser状态机错误.\n");
				return 0;
			}

		}
	}
//表示解析结束.有异常出现
	printf("declare表达式出错.找不到;结尾.");
	return 0;
}

